import { Group, RepeatWrapping, LineBasicMaterial, Vector3, SpriteMaterial, Sprite, Color, MeshStandardMaterial, DoubleSide,CylinderGeometry,Mesh,MeshBasicMaterial ,BoxGeometry,AdditiveBlending,PlaneGeometry,SRGBColorSpace} from "three"
import {  getBoundBox, emptyObject,GradientShader} from "@/mini3d"
import { ExtrudeMap } from "./extrudeMap"
import { geoMercator } from "d3-geo"
import { gsap } from "gsap"
export class ChildMap {
  constructor(parent, options) {
    console.log('子对象')
    console.log(options)
    this.parent = parent
    this.instance = new Group()
    this.instance.rotateX(-Math.PI / 2)
    this.instance.position.set(0, 0.2, 0)
    let defaultOptions = {
      adcode: 10000,
      center: [0, 0],
      centroid: [0, 0],
      childrenNum: 0,
      parentBoxSize: [1, 1], // 上级地图的尺寸
      mapData: {},
      geoProjectionCenter: [0, 0],
      geoProjectionScale: options.geoProjectionScale || 20,
      geoProjectionTranslate: [0, 0],
    }
    this.options = Object.assign({}, defaultOptions, options)
    this.labelGroup = new Group()
    // 保存圆柱体组
    this.barChartGroup = new Group();
    this.labelChildGroup = new Group()
    // 是否点击了
    this.clicked = false
    // 缩放值
    this.scale = 1
    // 地图的box大小
    this.boundBox = {}
    // 地图的区域数据
    this.areaData = []
    // 区域标签
    this.allAreaLabel = []
    // 区域标签组
    this.areaLabelGroup = new Group()
    // 区域点组
    this.areaPointGroup = new Group()
    // 信息标签组
    this.allInfoLabel = []
    this.infoLabelGroup = new Group()
    this.instance.add(this.areaLabelGroup)
    // 事件元素
    this.eventElement = []
    this.pointEventElement = []
    this.init()
  }
  init() {
    this.createModel()
    this.addLabel()
    this.createBarCharts(); // 添加这行
    if (this.options.childrenNum) {
      this.addEvent()
    }
    this.addPointEvent()
  }
  createModel() {
    let { map } = this.createMap()
    // this.setScale(map)
    map.setParent(this.instance)
    
    
  }
  createHUIGUANG(h, color) {
      let geometry = new PlaneGeometry(0.35, h)
      geometry.translate(0, h / 2, 0)
      const texture = this.parent.assets.instance.getResource("huiguang")
      texture.colorSpace = SRGBColorSpace
      texture.wrapS = RepeatWrapping
      texture.wrapT = RepeatWrapping
      let material = new MeshBasicMaterial({
        color: color,
        map: texture,
        transparent: true,
        opacity: 0.5,
        depthWrite: false,
        side: DoubleSide,
        blending: AdditiveBlending,
      })
      let mesh = new Mesh(geometry, material)
      mesh.renderOrder = 10
      mesh.rotateX(Math.PI / 2)
      let mesh2 = mesh.clone()
      let mesh3 = mesh.clone()
      mesh2.rotateY((Math.PI / 180) * 60)
      mesh3.rotateY((Math.PI / 180) * 120)
      return [mesh, mesh2, mesh3]
    }
  createQuan(position, index) {
    const guangquan1 = this.parent.assets.instance.getResource("guangquan1")
    const guangquan2 = this.parent.assets.instance.getResource("guangquan2")
    let geometry = new PlaneGeometry(0.5, 0.5)
    let material1 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan1,
      alphaMap: guangquan1,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    })
    let material2 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan2,
      alphaMap: guangquan2,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    })
    let mesh1 = new Mesh(geometry, material1)
    let mesh2 = new Mesh(geometry, material2)
    mesh1.renderOrder = 6
    mesh2.renderOrder = 6
    mesh1.rotateX(-Math.PI / 2)
    mesh2.rotateX(-Math.PI / 2)
    mesh1.position.copy(position)
    mesh2.position.copy(position)
    mesh2.position.y -= 0.001
    mesh1.scale.set(0, 0, 0)
    mesh2.scale.set(0, 0, 0)
    this.quanGroup = new Group()
    this.quanGroup.add(mesh1, mesh2)
    this.instance.add(this.quanGroup)
    this.parent.time.on("tick", () => {
      mesh1.rotation.z += 0.05
    })
    return this.quanGroup
  }
  
  createBarCharts(data,map) {
    data = data.map((item,index)=>{
      item.count = Math.round(10)*10
      return item
    })
    // 清除现有的子柱形图
    if (this.barChildGroup) {
      this.scene.remove(this.barChildGroup);
      this.barChildGroup.clear();
    } else {
      this.barChildGroup = new Group();
      this.barChildGroup.rotation.x = -Math.PI / 2; // 确保与地图旋转一致
    }

    // 初始化存储数组
    this.allChildBar = [];
    this.allChildBarMaterial = [];
    this.allChildGuangquan = [];
    this.allChildProvinceLabel = [];
    this.allChildProvinceNameLabel = [];

    // 确保数据有效
    if (!data || !Array.isArray(data)) {
      console.error('Invalid data provided to childrenCreateBar');
      return;
    }

    const factor = 0.3;
    const height = 4.0 * factor;
    const max = data[0]?.count || 100; // 默认最大值防止除零

    data.forEach((item, index) => {
      if (!item.centroid || !item.name) {
        console.warn('Invalid item in data:', item);
        return;
      }

      // 1. 创建光柱材质
      const material = new MeshBasicMaterial({
        color: 0xffffff,
        transparent: true,
        opacity: 1,
        depthTest: false,
        fog: false,
      });

      // 应用渐变着色器
      new GradientShader(material, {
        uColor1: index > 3 ? 0xfbdf88 : 0x50bbfe,
        uColor2: index > 3 ? 0xfffef4 : 0x77fbf5,
        size: height * (item.count / max),
        dir: "y",
      });

      // 2. 创建圆柱几何体
      const radius = 0.25 * factor;
      const geoHeight = height * (item.count / max);
      const geo = new CylinderGeometry(radius, radius, geoHeight, 32);
      // geo.rotateX(-Math.PI / 2); // 使圆柱沿Z轴竖立
      geo.translate(0, 0, geoHeight / 2);

      // 3. 创建光柱网格
      const mesh = new Mesh(geo, material);
      mesh.renderOrder = 5;

      // 4. 设置位置（关键修正点）
      let [x, y] = this.geoProjection(item.centroid);
      if (isNaN(x) || isNaN(y)) {
        console.error('Invalid coordinates for item:', item);
        return;
      }

      // 注意坐标系转换：地理坐标y需要取反
      mesh.position.set(x, -y, this.parent.depth + 20);
      mesh.scale.set(1, 1, 0); // 初始缩放为0，后续动画展开
      mesh.userData = { ...item };

      // 5. 添加光效
      const hg = this.createHUIGUANG(geoHeight, index > 3 ? 0xfffef4 : 0x50C2FF);
      mesh.add(...hg);

      // 6. 创建光圈底效
      const guangQuan = this.createQuan(new Vector3(x, this.parent.depth + 0.44, -y), index);
      this.allChildGuangquan.push(guangQuan);

      // 7. 添加到组
      this.barChildGroup.add(mesh);
      this.allChildBar.push(mesh);
      this.allChildBarMaterial.push(material);

      // 8. 创建标签
      const nameLabel = this.createChildNameLabel(item, index, new Vector3(x, -y, this.parent.depth + 0.1));
      this.allChildProvinceNameLabel.push(nameLabel);

      if (item.count > 0) {
        const barLabel = this.createChildBarLabel(item, index, new Vector3(x, -y, this.parent.depth + 1.1 + geoHeight));
        this.allChildProvinceLabel.push(barLabel);
      }
    });

    // 9. 添加到场景
    this.instance.add(this.barChildGroup);

    // 10. 动画显示
    this.animateChildBars();
  }
  // 辅助方法：创建子地图名称标签
  createChildNameLabel(data, index, position) {
    const label = this.parent.label3d.create("", "provinces-name-label", true);
    label.init(
      `<div class="provinces-name-label"><div class="provinces-name-label-wrap">${data.name}</div></div>`,
      position
    );
    this.parent.label3d.setLabelStyle(label, 0.018, "x");
    label.setParent(this.labelChildGroup);
    label.userData.adcode = data.adcode;
    label.userData.position = [position.x, position.y, position.z];
    return label;
  }

  // 辅助方法：创建子地图柱形图标签
  createChildBarLabel(data, index, position) {
    
    const label = this.parent.label3d.create("", "provinces-label", false);
    label.init(
      `<div class="provinces-label ${index > 4 ? "yellow" : ""}" style="background: none !important; transform: translateX(-50px);">
        <div class="provinces-label-wrap" style="background: none !important;">
          <div class="number"><span class="value">${data.count}</span><span class="unit">个</span></div>
        </div>
      </div>`,
      position
    );
    this.parent.label3d.setLabelStyle(label, 0.01, "x");
    label.setParent(this.labelChildGroup);
    label.userData.isBillboard = true;
    return label;
  }

  // 辅助方法：动画显示子柱形图
  animateChildBars() {
    const tl = gsap.timeline();
    
    this.allChildBar.forEach((bar, index) => {
      tl.to(bar.scale, {
        duration: 0.8,
        delay: index * 0.05,
        z: 1,
        ease: "back.out"
      }, "start");
    });

    this.allChildProvinceLabel.forEach((label, index) => {
      const element = label.element.querySelector(".provinces-label-wrap");
      tl.to(element, {
        duration: 0.5,
        delay: index * 0.05,
        opacity: 1,
        y: 0,
        ease: "power2.out"
      }, "start");
    });
  }
  // 创建省份
  createMap() {
    let mapJsonData = this.options.mapData
    let topNormal = this.parent.assets.instance.getResource("topNormal")
    topNormal.wrapS = topNormal.wrapT = RepeatWrapping

    this.mapLineMaterial = new LineBasicMaterial({
      color: 0x2CE2FE,
      opacity: 0,
      transparent: true,
      fog: false,
    })
    let [top, side] = this.parent.createProvinceMaterial()
    let topMaterial = top.clone()
    topMaterial.opacity = 1
    let sideMaterial = side.clone()
    sideMaterial.opacity = 1
    let faceMaterial = new MeshStandardMaterial({
      emissive: new Color(0x1364a8),
      emissiveIntensity: 2,
      transparent: true,
      opacity: 0.7,
      side: DoubleSide // 确保双面可见
    })
    faceMaterial.userData = {
      isSelected: false,
      originalPosition: null
    };

    // 直接修改材质着色器（确保在 GradientShader 之后）
    faceMaterial.onBeforeCompile = (shader) => {
      // 顶点着色器传递 uv
      shader.vertexShader = shader.vertexShader.replace(
        'void main() {',
        `
        varying vec2 vUv;
        void main() {
          vUv = uv;
        `
      );
    
      // 片元着色器添加 uniform 和 varying，放在全局声明区
      shader.fragmentShader = shader.fragmentShader.replace(
        'void main() {',
        `
        varying vec2 vUv;
        uniform vec3 uGlowColor;
        uniform float uGlowIntensity;
        uniform float uGlowRadius;
        uniform vec3 uColor1;
        uniform vec3 uColor2;
        void main() {
        `
      );
    }
      this.defaultMaterial = faceMaterial
      this.defaultLightMaterial = this.defaultMaterial.clone()
      this.defaultLightMaterial.color = new Color("#1364a8")
      this.defaultLightMaterial.opacity = 1
      this.defaultLightMaterial.emissive.setHex(new Color("#1364a8"));
      this.defaultLightMaterial.emissiveIntensity = 3.5;
  
    let map = new ExtrudeMap(this.parent, {
      geoProjectionScale:this.options.geoProjectionScale || this.geoProjectionScale,
      scale:this.scale,
      center: this.options.center,
      position: new Vector3(0, 0, 0.06),
      data: mapJsonData,
      depth: this.parent.depth+5,
      topFaceMaterial: this.defaultLightMaterial,
      sideMaterial: sideMaterial,
      lineMaterial: this.parent.mapLineMaterial,
      renderOrder: 9,
    })
    

     
    
    this.areaData = map.coordinates

    let { boxSize, box3 } = getBoundBox(map.mapGroup)

    map.mapGroup.children.map((group, index) => {
      group.children.map((mesh) => {
        if (mesh.type === "Mesh") {
          mesh.userData.type = "map"
          this.eventElement.push(mesh)
          this.parent.calcUv2(mesh.geometry, boxSize.x, boxSize.y, box3.min.x, box3.min.y)
        }
      })
    })
    this.setScale(map);
    return {
      map,
    }
  }

  addEvent() {
    let objectsHover = []

    const reset = (mesh) => {
      gsap.to(mesh.scale, {
        duration: 0.3,
        z: 1,
        onComplete: () => {
          mesh.traverse((obj) => {
            if (obj.isMesh) {
              obj.material[0].emissive.setHex(mesh.userData.materialEmissiveHex)
              obj.material[0].emissiveIntensity = 1
              obj.renderOrder = 9
            }
          })
        },
      })
      // 恢复柱形图状态
      // this.barChartGroup.children.forEach(cylinder => {
      //   if (cylinder.userData.areaData.adcode === mesh.userData.adcode) {
      //     cylinder.material.color.setHex(0x2CE2FE); // 恢复原色
      //     gsap.to(cylinder.scale, {
      //       y: 1,
      //       duration: 0.3
      //     });
      //   }
      // });

      this.setLabelMove(mesh.userData.adcode, "down")
      this.setPointMove(mesh.userData.adcode, "down")
    }
    const move = (mesh) => {
      gsap.to(mesh.scale, {
        duration: 0.3,
        z: 1.5,
      })

      this.setLabelMove(mesh.userData.adcode)
      this.setPointMove(mesh.userData.adcode)

      mesh.traverse((obj) => {
        if (obj.isMesh) {
          obj.material[0].emissive.setHex(0x0b112d)
          obj.material[0].emissiveIntensity = 1.5
          obj.renderOrder = 21
        }
      })
      // 高亮对应的柱形图
      // this.barChartGroup.children.forEach(cylinder => {
      //   if (cylinder.userData.areaData.adcode === mesh.userData.adcode) {
      //     cylinder.material.color.setHex(0xff0000); // 高亮颜色
      //     gsap.to(cylinder.scale, {
      //       y: 1.2,
      //       duration: 0.3
      //     });
      //   }
      // });
    }

    // 循环添加事件
    this.eventElement.map((mesh) => {
      this.parent.interactionManager.add(mesh)
      mesh.addEventListener("mousedown", (event) => {
        if (this.clicked) return false
        this.clicked = true
        let userData = event.target.parent.userData
        this.parent.history.push(userData)
        this.parent.loadChildMap(userData.name)
      })
      mesh.addEventListener("mouseup", (ev) => {
        this.clicked = false
      })
      mesh.addEventListener("mouseover", (event) => {
        if (!objectsHover.includes(event.target.parent)) {
          objectsHover.push(event.target.parent)
        }

        document.body.style.cursor = "pointer"
        move(event.target.parent)
      })
      mesh.addEventListener("mouseout", (event) => {
        objectsHover = objectsHover.filter((n) => n.userData.name !== event.target.parent.userData.name)
        if (objectsHover.length > 0) {
          const mesh = objectsHover[objectsHover.length - 1]
        }
        reset(event.target.parent)
        document.body.style.cursor = "default"
      })
    })
  }
  // 添加标点事件
  addPointEvent() {
    let objectsHover = []

    this.pointEventElement.map((mesh) => {
      this.parent.interactionManager.add(mesh)
      mesh.addEventListener("mousedown", (event) => {
        if (this.clicked) return false
        this.clicked = true
        let userData = event.target.userData
        this.allInfoLabel.map((label, index) => {
          label.hide()
          if (userData.index === index) {
            label.show()
          }
        })
      })
      mesh.addEventListener("mouseup", (ev) => {
        this.clicked = false
      })
      mesh.addEventListener("mouseover", (event) => {
        if (!objectsHover.includes(event.target.parent)) {
          objectsHover.push(event.target.parent)
        }

        document.body.style.cursor = "pointer"
        let sprite = event.target
        sprite.material = this.pointHoverMaterial.clone()
      })
      mesh.addEventListener("mouseout", (event) => {
        objectsHover = objectsHover.filter((n) => n.userData.name !== event.target.parent.userData.name)
        if (objectsHover.length > 0) {
          const mesh = objectsHover[objectsHover.length - 1]
        }

        document.body.style.cursor = "default"
        let sprite = event.target
        sprite.material = this.pointDefaultMaterial.clone()
      })
    })
  }
  // 设置标签移动
  setLabelMove(adcode, type = "up") {
    [...this.allAreaLabel].map((label) => {
      if (label.userData.adcode === adcode) {
        gsap.to(label.position, {
          duration: 0.3,
          z: type === "up" ? label.userData.position[2] + 3 / this.scale : label.userData.position[2],
        })
      }
    })
  }
  // 设置点移动
  setPointMove(adcode, type = "up") {
    this.areaPointGroup.children.map((point) => {
      if (point.userData.adcode === adcode) {
        gsap.to(point.position, {
          duration: 0.3,
          z: type === "up" ? point.userData.position[2] + 3 / this.scale : point.userData.position[2],
        })
      }
    })
  }
  addLabel() {
    // 贴图
    const texture = this.parent.assets.instance.getResource("point")

    const material = new SpriteMaterial({
      map: texture,
      color: 0xffffff,
      transparent: true,
      depthTest: false,
    })
    this.pointDefaultMaterial = material
    this.pointHoverMaterial = material.clone()
    this.pointHoverMaterial.color = new Color(0x2CE2FE)
    const sprite = new Sprite(material)
    sprite.renderOrder = 23
    this.areaData.map((item, index) => {
      
      let [x, y] = this.geoProjection(item.centroid)
      // 名称
      let nameLabel = this.labelNameStyle(item, index, new Vector3(x, -y, 0))
      this.allAreaLabel.push(nameLabel)
      // 信息
      let infoLabel = this.infoLabel(item, index, new Vector3(x, -y, 0))
      this.allInfoLabel.push(infoLabel)

      //点
      let areaPoint = sprite.clone()
      sprite.material = material.clone()
      areaPoint.position.set(x, -y, 0)
      areaPoint.userData.adcode = item.adcode

      areaPoint.userData.type = "point"
      areaPoint.userData.name = item.name
      areaPoint.userData.position = [x, -y, 0]
      areaPoint.userData.index = index
      this.areaPointGroup.add(areaPoint)
    })
    this.setNameScale()
    this.setInfoScale()
    this.setPointScale()
  }
  infoLabel(data, index, position) {
    let label3d = this.parent.label3d
    let label = label3d.create("", "info-point", true)

    label.init(
      ` <div class="info-point-wrap">
      <div class="info-point-wrap-inner">
        <div class="info-point-line">
          <div class="line"></div>
          <div class="line"></div>
          <div class="line"></div>
        </div>
        <div class="info-point-content">
          <div class="content-item"><span class="label">名称</span><span class="value">${data.name}</span></div>
          <div class="content-item"><span class="label">PM2.5</span><span class="value">100ug/m²</span></div>
          <div class="content-item"><span class="label">等级</span><span class="value">良好</span></div>
        </div>
      </div>
    </div>
  `,
      position
    )
    label3d.setLabelStyle(label, 0.06 / this.scale, "x")
    label.setParent(this.infoLabelGroup)
    // label.hide()
    return label
  }

  
  // 城市标签
  labelNameStyle(data, index, position) {

    console.log("城市标签A")
    console.log(data)
    console.log(position)
    // position.x = position.x * 120
    // position.y = position.y * 120
    let label3d = this.parent.label3d
    let label = label3d.create("", "area-name-label", true)
    label.init(`<div class="area-name-label-wrap">${data.name}</div>`, position)
    label3d.setLabelStyle(label, 0.08 / this.scale, "x")
    label.setParent(this.areaLabelGroup)
    label.userData.adcode = data.adcode
    label.userData.position = [position.x, position.y, position.z]
    return label

  }

  calculateScale(parentBoxSize, boxSize) {
    let xScale = parentBoxSize[0] / boxSize[0]
    let yScale = parentBoxSize[1] / boxSize[1]
    let scale = Math.min(xScale, yScale)

    return scale
  }

  setScale(map) {
    let { parentBoxSize } = this.options
    let boundBox = getBoundBox(map.mapGroup)

    let scale = this.calculateScale(parentBoxSize, [boundBox.boxSize.x, boundBox.boxSize.y])

    // 子地图缩放到主地图大小
    map.mapGroup.scale.set(scale, scale, 1)
    let boundBox1 = getBoundBox(map.mapGroup)
    // 放大后，中心坐标有偏移，偏移了多少，就反向移动多少
    map.mapGroup.position.x = -boundBox1.center.x
    map.mapGroup.position.y = -boundBox1.center.y
    this.scale = scale
    this.boundBox = boundBox1
  }

  setNameScale() {

    this.areaLabelGroup.scale.set(this.scale, this.scale, this.scale)

    this.areaLabelGroup.position.x = -this.boundBox.center.x
    this.areaLabelGroup.position.y = -this.boundBox.center.y
    console.log(this.areaLabelGroup)
    this.allAreaLabel.map((label) => {
      console.log("label偏移=========")
      console.log(label.position)
      console.log(this.scale)
      console.log(this.parent.depth)
      
      let z = (this.parent.depth * 10 + 0.4) / this.scale
      label.position.z = z 
      console.log(z)

      label.position.y -= 1.5 / this.scale
      label.userData.position = [label.position.x, label.position.y, label.position.z]
    })

    
  }

  setPointScale() {
    this.areaPointGroup.scale.set(this.scale, this.scale, this.scale)

    this.areaPointGroup.position.x = -this.boundBox.center.x
    this.areaPointGroup.position.y = -this.boundBox.center.y
    this.areaPointGroup.children.map((point) => {
      let z = (this.parent.depth + 1.4) / this.scale
      point.position.z = z
      point.userData.position[2] = z

      point.scale.set(5 / this.scale, 5 / this.scale, 5 / this.scale)

      point.userData.position = [point.position.x, point.position.y, point.position.z]

      this.pointEventElement.push(point)
    })
  }

  setInfoScale() {
    this.infoLabelGroup.scale.set(this.scale, this.scale, this.scale)

    this.infoLabelGroup.position.x = -this.boundBox.center.x
    this.infoLabelGroup.position.y = -this.boundBox.center.y
    this.infoLabelGroup.children.map((point) => {
      let z = (this.parent.depth + 10) / this.scale
      point.position.z = z

      point.scale.set(0.06 / this.scale, 0.06 / this.scale, 0.06 / this.scale)
    })
  }
  geoProjection = (args) => {
    
    let { geoProjectionScale, geoProjectionTranslate, center } = this.options
    console.log('子地图三参数==========')
    console.log(center)
    console.log(geoProjectionScale)
    console.log(geoProjectionTranslate)
    
    return geoMercator().center(center).scale(120).translate(geoProjectionTranslate)(args)
  }

  setParent(parent) {
    parent.add(this.instance)
  }

  destroy() {
    ;[...this.allAreaLabel, ...this.allInfoLabel].map((label) => {
      label.remove()
    })
    this.removeElement(".area-name-label")
    this.removeElement(".info-point")
    ;[...this.eventElement, ...this.pointEventElement].map((mesh) => {
      this.parent.interactionManager.remove(mesh)
    })

    emptyObject(this.instance)
  }
  removeElement(elementClassName) {
    var elements = document.querySelectorAll(elementClassName)
    for (let i = 0; i < elements.length; i++) {
      const element = elements[i]
      const parent = element.parentNode
      parent.removeChild(element)
    }
  }
}
